package com.zxjbyte.yiyi.framework.quartz.trigger.route;

import cn.hutool.core.lang.Assert;
import com.zxjbyte.yiyi.framework.common.exception.ServiceException;
import org.quartz.*;

/**
 * Cron表达式触发器
 *
 * CronTrigger基于Cron表达式定义触发规则。Cron表达式是一种灵活的、精确到秒的时间表达式，允许你定义非常灵活的定时任务规则。
 * 比如，你可以指定每天的某个时刻触发任务，或者每周的某个具体时刻触发任务。
 *
 * @Author zhangxingjia
 * @Date 2023/10/8 15:39
 * @Version: 1.0
 */
public class CronTriggerHelper {

    /**
     * 创建一个自定义Cron表达式触发器
     * @param cronExpression Cron表达式
     * @return
     */
    public static CronScheduleBuilder customCronSchedule(String cronExpression){
        Assert.isTrue(CronExpression.isValidExpression(cronExpression), () -> new ServiceException("Cron表达式无效"));
        return CronScheduleBuilder.cronSchedule(cronExpression);
    }


    /**
     * 创建一个自定义Cron表达式触发器
     * @param cronExpression Cron表达式
     * @param misfireInstruction 哑火策略
     * @return
     */
    public static CronScheduleBuilder customCronSchedule(String cronExpression, int misfireInstruction){
        CronScheduleBuilder cronSchedule = customCronSchedule(cronExpression);
        misfirePolicy(cronSchedule, misfireInstruction);
        return cronSchedule;
    }

    /**
     * 创建一个每天固定时间执行的触发器（例如，每天下午 3 点执行）
     * @param hour
     * @param minute
     * @return
     */
    public static CronScheduleBuilder dailyAtSpecificTime(int hour, int minute){
        return CronScheduleBuilder.dailyAtHourAndMinute(hour, minute);
    }


    /**
     * 创建一个每周在指定的星期几、小时和分钟的触发器
     * @param dayOfWeek 范围从1到7，分别代表周日到周六。例如，1表示周日，2表示周一，依此类推。
     * @param hour 范围从0到23，表示一天中的小时
     * @param minute 范围从0到59，表示小时内的分钟数
     * @return
     */
    public static CronScheduleBuilder weeklyAtSpecificTime(int dayOfWeek, int hour, int minute){
        return CronScheduleBuilder.weeklyOnDayAndHourAndMinute(dayOfWeek, hour, minute);
    }

    /**
     * 创建一个每天凌晨执行的触发器
     * @return
     */
    public static CronScheduleBuilder dailyZeroTime(){
        return dailyAtSpecificTime(0,0);
    }


    /**
     * 哑火策略
     * 详细介绍参考资料：https://www.cnblogs.com/yaopengfei/p/8549508.html
     * @param cronSchedule
     * @param misfireInstruction
     */
    private static void misfirePolicy(CronScheduleBuilder cronSchedule, int misfireInstruction){
        if(misfireInstruction == CronTrigger.MISFIRE_INSTRUCTION_FIRE_ONCE_NOW){
            cronSchedule.withMisfireHandlingInstructionFireAndProceed();
        } else if (misfireInstruction == CronTrigger.MISFIRE_INSTRUCTION_DO_NOTHING){
            cronSchedule.withMisfireHandlingInstructionDoNothing();
        } else if (misfireInstruction == CronTrigger.MISFIRE_INSTRUCTION_IGNORE_MISFIRE_POLICY){
            cronSchedule.withMisfireHandlingInstructionIgnoreMisfires();
        }
    }

}
